/**
 *  Copyright (C) 2008-2013  Telosys project org. ( http://www.telosys.org/ )
 *
 *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *          http://www.gnu.org/licenses/lgpl.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.telosys.persistence.connection;

import java.util.Properties;

import org.telosys.common.logger.TelosysClassLogger;
import org.telosys.persistence.database.DatabaseConfig;
import org.telosys.util.StrUtil;

public class ConnectionProviderManager {
	
    private static final TelosysClassLogger log = new TelosysClassLogger(ConnectionProviderManager.class);
	
    //---------------------------------------------------------------------------
//    /**
//     * Creates a Connection Provider according with the "db" configuration tag parameters
//     * 
//     * @param sDbId
//     * @param sDbName
//     * @param sDataSource
//     * @param sDbDriver
//     * @param sDbUrl
//     * @param props
//     * @param sDbIsolationLevel
//     * @param sDbPoolSize
//     * @return the ConnectionProvider created
//     */
    //public static ConnectionProvider createConnectionProvider(String sDbId, String sDbName, String sDataSource, String sDbDriver, String sDbUrl, Properties props, String sDbIsolationLevel, String sDbPoolSize)
    
    /**
     * Creates a Connection Provider for the given database configuration
     * @param databaseConfig
     * @return
     */
    public static ConnectionProvider createConnectionProvider( DatabaseConfig databaseConfig )
    {
    	//--- Database configuration information :
    	int    dbId   = databaseConfig.getId() ;
    	String dbName = databaseConfig.getName() ;
    	
    	String connectionProviderCustomClass = databaseConfig.getConnectionProviderCustomClass() ;
    	String dataSourceName = databaseConfig.getDataSourceName() ;
    	
    	String jdbcDriver = databaseConfig.getDriver() ;
    	String jdbcURL    = databaseConfig.getJdbcURL() ;
    	Properties properties = databaseConfig.getProperties() ;
    	int    isolationLevel = databaseConfig.getIsolationLevel() ; 
    	int    poolSize = databaseConfig.getPoolSize() ;
    	

    	
        log.trace("createConnectionProvider : id=" + dbId + " name=" + dbName + " datasource=" + dataSourceName + " driver=" + jdbcDriver 
        		+ " url=" + jdbcURL + " poolSize=" + poolSize + " isolation level=" + isolationLevel);

        ConnectionProvider connectionProvider = null;
        if ( ! StrUtil.nullOrVoid(connectionProviderCustomClass) )
        {
        	//--- There's a specific custom class for the ConnectionProvider implementation => use it 
            log.info("DB " + dbId + " (" + dbName + ") : Create ConnectionProvider : Custom class '" + connectionProviderCustomClass + "' ...");
        	createCustomClassConnectionProvider(dbId, dbName, connectionProviderCustomClass);
        }
        else if ( ! StrUtil.nullOrVoid(dataSourceName) )
        {
        	//--- There's a JDBC DataSource name => use it  
            log.info("DB " + dbId + " (" + dbName + ") : Create ConnectionProvider : DataSource '" + dataSourceName + "' ...");
//            try
//            {
//                cp = new SqlDataSource(sDbName, sDataSource);
//            } catch (TelosysException e)
//            {
//                log.error("Cannot create SqlDataSource : TelosysException : " + e.getMessage());
//                return null;
//            }
            //connectionProvider = new ConnectionProviderDataSource(dbName, dataSourceName);
            connectionProvider = new ConnectionProviderDataSource( dataSourceName );
        }
        else if (poolSize > 1)
        {
            log.trace("DB " + dbId + " (" + dbName + ") driver    = " + jdbcDriver);
            log.trace("DB " + dbId + " (" + dbName + ") url       = " + jdbcURL);

//            int iDbPoolSize = StrUtil.getInt(sDbPoolSize, 0);
            log.trace("DB " + dbId + " (" + dbName + ") pool size = " + poolSize );

            log.trace("DB " + dbId + " (" + dbName + ") isolation level = " + isolationLevel );

            //--- Connection Pool
            log.info("DB " + dbId + " (" + dbName + ") : Create ConnectionProvider : Telosys Pool (initial size=" + poolSize + ") ...");
            //connectionProvider = new ConnectionProviderPool(dbName, jdbcDriver, jdbcURL, properties, isolationLevel, poolSize);
            connectionProvider = new ConnectionProviderPool( jdbcDriver, jdbcURL, properties, isolationLevel, poolSize);
        }
        else
        {
            //--- No pool ( simple Connection Factory )
            log.info("DB " + dbId + " (" + dbName + ") : Create ConnectionProvider : Telosys Single Connection ...");
            //connectionProvider = new ConnectionProviderSingle(dbName, jdbcDriver, jdbcURL, properties, isolationLevel);
            connectionProvider = new ConnectionProviderSingle( jdbcDriver, jdbcURL, properties, isolationLevel);
        }
        return connectionProvider;
    }
    
    //---------------------------------------------------------------------------
    /**
     * Creates a Connection Provider based on a specific custom class, according with the "db" configuration tag parameters
     * 
     * @param sDbId
     * @param sDbName
     * @param sCustomClass
     * @return
     * @since v 1.0.1
     */
    private static ConnectionProvider createCustomClassConnectionProvider(int dbId, String sDbName, String sCustomClass)
    {
        //--- Try to load the custom class 
        //Class clazz = null ;
        Class<?> clazz = null ; // v 1.2.0 ( Java 5 )
        try
        {
            clazz = Class.forName(sCustomClass);
        } catch (ClassNotFoundException e)
        {
            log.error("Cannot load ConnectionProvider custom class : '"+sCustomClass+"' (ClassNotFoundException)" ); 
            return null ;
        }
        
        //--- Try to create an instance from the custom class 
        Object obj = null ;
        try
        {
            obj = clazz.newInstance();
        } catch (InstantiationException e1)
        {
            log.error("Cannot create instance from class : '"+sCustomClass+"' (InstantiationException)" ); 
            return null ;
        } catch (IllegalAccessException e1)
        {
            log.error("Cannot create instance from class : '"+sCustomClass+"' (IllegalAccessException)" ); 
            return null ;
        }
        
        //--- Check interface implementation
        if ( obj instanceof ConnectionProvider )
        {
            // OK : return it
            return (ConnectionProvider) obj; 
        }
        else
        {
            log.error("Custom class '"+sCustomClass+"' does not implement ConnectionProvider interface");
            return null ;
        }
    }
    
    
//    //---------------------------------------------------------------------------
//    private static boolean isValidDataSource(String sDataSource)
//    {
//        if (sDataSource != null)
//        {
//            if (sDataSource.trim().length() > 0)
//            {
//                return true;
//            }
//        }
//        return false;
//    }
//


}
